﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace OnlineGameLibrary.MessageEx
{
    static public class MessageUtil
    {
        const string _real_action = "http://gameaction";
        const string _sys_ns = "http://gamemessage";

        //public const string GameRoomNamespace = "";
        //public const string GameNamespace = "";

        #region system header define
        const string _sys_scope = "scope";
        public static string GetScope(this Message msg)
        {
            var scope = msg.Headers.GetHeader<string>(_sys_scope,_sys_ns);
            return scope;
        }
        static Message SetScope(this Message msg, string scope)
        {
            msg.Headers.Add(
                MessageHeader.CreateHeader(_sys_scope, _sys_ns, scope));
            return msg;
        }

        const string _sys_action = "action";
        public static string GetAction(this Message msg)
        {
            var action = msg.Headers.GetHeader<string>(_sys_action, _sys_ns);
            return action;
        }
        static Message SetAction(this Message msg, string action)
        {
            msg.Headers.Add(
                MessageHeader.CreateHeader(_sys_action, _sys_ns, action));
            return msg;
        }

        const string _game_aud = "gameaudience";
        public static Message SetAudience(this Message msg, IList<string> plist)
        {
            msg.Headers.Add(
                MessageHeader.CreateHeader(_game_aud, _sys_ns, plist));
            return msg;
        }
        public static List<string> GetAudience(this Message msg)
        {
            if (msg.Headers.FindHeader(_game_aud, _sys_ns) == -1)
                return null;

                var list = msg.Headers.GetHeader<List<string>>(_game_aud, _sys_ns);
                return list;
        }

        const string _game_due = "gameduetime";
        public static Message SetDueTime(this Message msg, DateTime duetime)
        {
            msg.Headers.Add(
                MessageHeader.CreateHeader(_game_due, _sys_ns, duetime));
            return msg;
        }
        public static DateTime GetDueTime(this Message msg)
        {
            if (msg.Headers.FindHeader(_game_due, _sys_ns) == -1)
                return DateTime.MaxValue;

            var duetime = msg.Headers.GetHeader<DateTime>(_game_due, _sys_ns);
            return duetime;
        }
        #endregion

        static MessageVersion _msgver = MessageVersion.Soap12WSAddressing10;
        static public Message CreateMessage(this MessageDefine msgdef, object body, params object[] headers)
        {
            if (headers.Length != msgdef.HeaderDefines.Count)
                throw new Exception("header count not correct");

            var message = Message.CreateMessage(_msgver, _real_action, body);

            MessageUtil.SetScope(message, msgdef.Namespace);
            MessageUtil.SetAction(message, msgdef.Action);

            for (int i = 0; i < headers.Length; i++)
            {
                message.Headers.Add(
                    MessageHeader.CreateHeader(msgdef.HeaderDefines[i].HeaderName, msgdef.Namespace, headers[i]));
            }
            return message;
        }

        static public MessageContent GetMessage(this MessageDefine msgdef, Message msg)
        {
            if (!msgdef.IsMessageMatch(msg))
                throw new Exception("message action not match");
            var ret = new MessageContent();
            ret.MessageDefine = msgdef;

            var getbodymethod = typeof(Message).GetMethod("GetBody", new Type[] { });
            var invokemethod = getbodymethod.MakeGenericMethod(msgdef.BodyType);
            ret.MessageBodyContent = invokemethod.Invoke(msg, new object[] { });

            foreach (var header in msgdef.HeaderDefines)
            {
                var getheadermethod = typeof(MessageHeaders).GetMethod("GetHeader", new Type[] { typeof(string), typeof(string) });
                var invokemethod2 = getheadermethod.MakeGenericMethod(header.ValueType);
                ret.HeaderContents.Add(invokemethod2.Invoke(msg.Headers,
                    new object[] { header.HeaderName, msgdef.Namespace }));
            }

            return ret;
        }
    }
}
